package org.spring.aicloud.controller.model;

import com.alibaba.cloud.ai.tongyi.chat.TongYiChatClient;
import com.alibaba.cloud.ai.tongyi.image.TongYiImagesClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.spring.aicloud.entity.Answer;
import org.spring.aicloud.entity.myenum.AiModelEnum;
import org.spring.aicloud.entity.myenum.AiTypeEnum;
import org.spring.aicloud.service.IAnswerService;
import org.spring.aicloud.util.AppVariable;
import org.spring.aicloud.util.MinioUtil;
import org.spring.aicloud.util.ResponseEntity;
import org.spring.aicloud.util.SecurityUtil;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.image.Image;
import org.springframework.ai.image.ImagePrompt;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Base64;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/tongyi")
@Tag(name = "通义大模型")
public class TongyiController {

    @Resource
    private TongYiChatClient chatClient;
    @Resource
    private TongYiImagesClient imagesClient;
    @Resource
    private IAnswerService answerService;
    @Resource
    private MinioUtil minIoUtil;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private RedisTemplate<String,Object> redisTemplate;
    /**
     * 通义千问的聊天
     *
     * @param question
     * @return
     */
    @RequestMapping("/chat")
    public ResponseEntity chat(String question) {
        if (!StringUtils.hasLength(question)) {
            return ResponseEntity.fail("问题不能为空!");
        }
        //在调用接口之前，先针对用户加锁
        //创建key
        String lockKey = AppVariable.getModelLockKey
                (SecurityUtil.getCurrentUser().getUid(),
                        AiModelEnum.TONGYI.getValue(), AiTypeEnum.CHAT.getValue());
        String result = ""; //大模型返回的结果
        boolean addResult = false;//数据是否保存成功
        //创建分布式锁实例
        RLock lock = redissonClient.getLock(lockKey);
        //尝试获取分布式锁
        boolean isLock = false;
        try {
            isLock = lock.tryLock(10, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        if (!isLock) {
            //获取分布式锁失败
            return ResponseEntity.fail("请勿频繁调用接口");
        }
        try {
            result = chatClient.call(new Prompt(question))
                    .getResult()
                    .getOutput()
                    .getContent();
            //将结果保存到数据库
            addResult = answerService.save(Answer.builder()
                    .title(question)
                    .content(result)
                    .type(AiTypeEnum.CHAT.getValue())
                    .model(AiModelEnum.TONGYI.getValue())
                    .uid(SecurityUtil.getCurrentUser().getUid()).build());
        } catch (Exception ignored) {
        } finally {
            //3.释放锁
            lock.unlock();
        }
        if (addResult) {
            return ResponseEntity.success(result);
        }
        return ResponseEntity.fail("操作失败!");
    }

    /**
     * 通义千问的绘画
     *
     * @param question
     * @return
     */
    @RequestMapping("/draw")
    public ResponseEntity draw(String question) {
        if (!StringUtils.hasLength(question)) {
            return ResponseEntity.fail("问题不能为空!");
        }
        //在调用接口之前，先针对用户加锁
        //创建key
        String lockKey = AppVariable.getModelLockKey
                (SecurityUtil.getCurrentUser().getUid(),
                        AiModelEnum.TONGYI.getValue(), AiTypeEnum.DRAW.getValue());
        String url = ""; //大模型返回的结果
        boolean addResult = false;//数据是否保存成功
        //创建分布式锁实例
        RLock lock = redissonClient.getLock(lockKey);
        //尝试获取分布式锁
        boolean isLock = false;
        try {
            isLock = lock.tryLock(10, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        if (!isLock) {
            //获取分布式锁失败
            return ResponseEntity.fail("请勿频繁调用接口");
        }
        try {
            Image image = imagesClient.call(new ImagePrompt(question)).getResult().getOutput();
            String b64Json = image.getB64Json();
            url = "";
            try (InputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(b64Json))) {
                String fileName = "ty-draw-" + UUID.randomUUID().toString().replace("-", "");
                url = minIoUtil.upload(fileName, inputStream, "image/png");
            } catch (Exception e) {
                return ResponseEntity.fail("图片生成失败，请重试!");
            }
            //将结果保存到数据库
            addResult = answerService.save(Answer.builder()
                    .title(question)
                    .content(url)
                    .type(AiTypeEnum.DRAW.getValue())
                    .model(AiModelEnum.TONGYI.getValue())
                    .uid(SecurityUtil.getCurrentUser().getUid()).build());
        }catch (Exception ignored){}
        finally {
            //3.释放锁
            lock.unlock();
        }
        if (addResult) {
            return ResponseEntity.success(url);
        }
        return ResponseEntity.fail("操作失败，请重试!");
    }

    /**
     * 获取通义千问下的聊天记录
     *
     * @return
     */
    @RequestMapping("/getchatlist")
    public ResponseEntity getChatList() {
        //首先获取到当前的登录用户和调用的大模型
        long uid = SecurityUtil.getCurrentUser().getUid();
        int type = AiTypeEnum.CHAT.getValue();
        int model = AiModelEnum.TONGYI.getValue();
        //将当前的uid和type和model封装成一个key
        String cacheKey = AppVariable.getListCacheKey(uid,model,type);
        Object value = redisTemplate.opsForValue().get(cacheKey);
        if (value == null) {
            //查询当前用户下的指定大模型下的聊天功能下的聊天记录
            QueryWrapper<Answer> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("uid", SecurityUtil.getCurrentUser().getUid());
            queryWrapper.eq("type", 1);
            queryWrapper.eq("model", 2);
            queryWrapper.orderByDesc("aid");
            List<Answer> list = answerService.list(queryWrapper);
            //查询到结果之后存储到缓存当中
            redisTemplate.opsForValue().set(cacheKey,list,1,TimeUnit.DAYS );
            //存储完成之后，将查询结果返回
            return ResponseEntity.success(list);
        }
        return ResponseEntity.success(value);
    }

    /**
     * 获取通义千问下的历史绘画列表
     */
    @RequestMapping("/getdrawlist")
    public ResponseEntity getDrawList() {
        QueryWrapper<Answer> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("uid", SecurityUtil.getCurrentUser().getUid());
        queryWrapper.eq("type", AiTypeEnum.DRAW.getValue());
        queryWrapper.eq("model", AiModelEnum.TONGYI.getValue());
        queryWrapper.orderByDesc("aid");
        List<Answer> list = answerService.list(queryWrapper);
        return ResponseEntity.success(list);
    }
}
